﻿// StorageLocationService.cs
using IService;
using IRepository;
using Entity;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Dapper;

namespace Service
{
    public class StorageLocationService : IStorageLocationService
    {
        private readonly IStorageLocationRepository _storageLocationRepo;
        private readonly IWarehouseRepository _warehouseRepo; // 注入仓库Repository用于校验关联
        private readonly ILogger<StorageLocationService> _logger; // 日志
        private readonly IHttpContextAccessor _httpContextAccessor; // 新增字段
        // 构造函数注入新增依赖
        public StorageLocationService(
            IStorageLocationRepository storageLocationRepo,
            IWarehouseRepository warehouseRepo,
            ILogger<StorageLocationService> logger,
            IHttpContextAccessor httpContextAccessor)
        {
            _storageLocationRepo = storageLocationRepo;
            _warehouseRepo = warehouseRepo;
            _logger = logger;
            _httpContextAccessor = httpContextAccessor; // 赋值
        }
        // 新增获取当前用户的方法（参考WarehouseRepository）
        private string GetCurrentUserName()
        {
            if (_httpContextAccessor?.HttpContext == null)
                return "system";

            try
            {
                // 从Session获取
                var session = _httpContextAccessor.HttpContext.Session;
                if (session.TryGetValue("LoginUserName", out byte[] userBytes))
                {
                    var userName = System.Text.Encoding.UTF8.GetString(userBytes);
                    if (!string.IsNullOrEmpty(userName))
                        return userName;
                }

                // 从Claims获取
                var claim = _httpContextAccessor.HttpContext.User?.FindFirst(System.Security.Claims.ClaimTypes.Name);
                if (claim != null && !string.IsNullOrEmpty(claim.Value))
                    return claim.Value;

                return "system";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取当前用户失败");
                return "system";
            }
        }
        public async Task<PaginationResult<StorageLocationEntity>> GetPagedListAsync(PaginationQuery query)
        {
            return await _storageLocationRepo.GetPagedListAsync(query);
        }

        public async Task DeleteAsync(int id)
        {
            _logger.LogInformation("Service层：开始处理库位删除，ID：{LocationId}", id);
            try
            {
                // 校验1：库位是否已关联仓库（如果已关联则禁止删除）
                var isRelated = await CheckIfLocationRelatedToWarehouse(id);
                if (isRelated)
                {
                    throw new InvalidOperationException($"库位ID：{id}已关联仓库，无法删除");
                }

                // 执行删除
                await _storageLocationRepo.DeleteAsync(id);
                _logger.LogInformation("Service层：库位删除成功，ID：{LocationId}", id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Service层：库位删除失败，ID：{LocationId}", id);
                throw;
            }
        }

        public async Task DeleteBatchAsync(int[] ids)
        {
            _logger.LogInformation("Service层：开始处理库位批量删除，ID列表：{Ids}", string.Join(",", ids));
            try
            {
                // 校验1：批量检查是否有库位已关联仓库
                foreach (var id in ids)
                {
                    var isRelated = await CheckIfLocationRelatedToWarehouse(id);
                    if (isRelated)
                    {
                        throw new InvalidOperationException($"库位ID：{id}已关联仓库，无法批量删除");
                    }
                }

                // 执行批量删除
                await _storageLocationRepo.DeleteBatchAsync(ids);
                _logger.LogInformation("Service层：库位批量删除成功，ID列表：{Ids}", string.Join(",", ids));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Service层：库位批量删除失败，ID列表：{Ids}", string.Join(",", ids));
                throw;
            }
        }

        // 辅助方法：检查库位是否已关联仓库
        private async Task<bool> CheckIfLocationRelatedToWarehouse(int locationId)
        {
            // 假设库位表的warehouse_id不为0即表示已关联
            // 实际需根据你的表结构调整（例如查询仓库关联表）
            var sql = "SELECT COUNT(1) FROM wms_basic_storage_location WHERE location_id = @Id AND warehouse_id != 0 AND is_delete = 0";
            var count = await _storageLocationRepo.GetDbConnection().ExecuteScalarAsync<int>(sql, new { Id = locationId });
            return count > 0;
        }
        public async Task<int> AddAsync(StorageLocationDTO dto)
        {
            _logger.LogInformation("Service层：开始处理库位新增，名称：{LocationName}", dto.LocationName);
            try
            {
                // 1. 参数校验
                if (string.IsNullOrWhiteSpace(dto.LocationNumber))
                    throw new ArgumentException("库位编号不能为空");
                if (string.IsNullOrWhiteSpace(dto.LocationName))
                    throw new ArgumentException("库位名称不能为空");
                if (dto.LocationCapacity <= 0)
                    throw new ArgumentException("库位容量必须大于0");
                if (dto.LocationManager <= 0)
                    throw new ArgumentException("请选择库位主管");

                // 2. 获取当前登录用户（需注入IHttpContextAccessor，参考仓库的GetCurrentUserName方法）
                var currentUser = GetCurrentUserName(); // 假设已有工具类获取当前用户

                // 3. 转换DTO为实体
                var entity = new StorageLocationEntity
                {
                    location_number = dto.LocationNumber,
                    location_name = dto.LocationName,
                    storage_location_capacity = dto.LocationCapacity,
                    users_id = dto.LocationManager,
                    sorting = dto.LocationSorting,
                    location_status = dto.LocationStatus,
                    note = dto.LocationNote,
                    warehouse_id = 0, // 新增时暂未关联仓库（后续可通过其他接口关联）
                    create_by = currentUser,
                    create_time = DateTime.Now,
                    update_by = currentUser,
                    update_time = DateTime.Now,
                    is_delete = 0
                };

                // 4. 调用Repository新增
                var newId = await _storageLocationRepo.AddAsync(entity);
                _logger.LogInformation("Service层：库位新增成功，ID：{NewId}", newId);
                return newId;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Service层：库位新增失败，名称：{LocationName}", dto.LocationName);
                throw;
            }
        }
        public async Task<int> AddAsync(StorageLocationAddDTO dto, int warehouseId = 0)
        {
            _logger.LogInformation("Service层：开始处理库位新增，编号：{LocationNumber}，关联仓库ID：{WarehouseId}", dto.location_number, warehouseId);
            try
            {
                // 补充：参数合法性校验（业务层前置校验）
                if (dto == null)
                    throw new ArgumentNullException(nameof(dto), "库位参数不能为空");
                if (string.IsNullOrWhiteSpace(dto.location_number))
                    throw new ArgumentException("库位编号不能为空");
                if (string.IsNullOrWhiteSpace(dto.location_name))
                    throw new ArgumentException("库位名称不能为空");
                if (dto.storage_location_capacity <= 0)
                    throw new ArgumentException("库位容量必须大于0");
                if (dto.users_id <= 0)
                    throw new ArgumentException("请选择库位主管");

                // 调用仓储层新增（原有逻辑保持不变）
                return await _storageLocationRepo.AddAsync(dto, warehouseId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Service层：库位新增失败，编号：{LocationNumber}", dto?.location_number);
                throw; // 抛出异常，让控制器捕获并返回给前端
            }
        }
        /// <summary>
        /// 实现带仓库ID过滤的库位分页查询
        /// </summary>
        public async Task<PaginationResult<StorageLocationEntity>> GetPagedListAsync(int? warehouseId, PaginationQuery pagination)
        {
            _logger.LogInformation("【库位服务】分页查询库位，warehouseId：{WarehouseId}", warehouseId);
            // 直接调用仓储的新方法
            return await _storageLocationRepo.GetPagedListAsync(warehouseId, pagination);
        }
    }
}